﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace Workflows.Components.Entities.Distances.FieldDistances
{
    public class DateTimeComparer:IAttributeDistanceCalcutor
    {
        #region IAttributeComparer Members

        /// <summary>
        /// load dictionary into memory or read config settings from file
        /// </summary>
        public void InitInMemorySettings()
        {
            
        }

        public double Compare(object attrValue1, object attrValue2, ref MatchResult result)
        {
            result = MatchResult.NullMatch;
            if (attrValue1 == null || attrValue2 == null)
                return 0;

            string strVal1 = attrValue1.ToString();
            string strVal2 = attrValue2.ToString();
            if (strVal1.Length == 0 || strVal2.Length == 0)
                return 0;

            DateTime date1 = DateTime.Parse(strVal1.ToString());
            DateTime date2 = DateTime.Parse(strVal2.ToString());
            if (date1 == date2)
            {
                result = MatchResult.PerfectMatch;
                return 1.00;
            }
            else
            {
                result = MatchResult.PositiveMatch;
                if (new TimeSpan(Math.Abs(date1.Ticks - date2.Ticks)).Days == 1)
                {
                    return 0.80;
                }
                else if (date1.Year == date2.Year && date1.Day == date2.Day)
                {
                    if (Math.Abs(date1.Month - date2.Month) == 1)
                        return 0.75;
                }
                else if (date1.Month == date2.Month && date1.Day == date2.Day)
                {
                    if (Math.Abs(date1.Year - date2.Year) == 1)
                        return 0.70;
                }

                string dateStr1 = date1.Year.ToString() +
                                  (date1.Month >= 10 ? date1.Month.ToString() : "0" + date1.Month.ToString()) +
                                  (date1.Day >= 10 ? date1.Day.ToString() : "0" + date1.Day.ToString());
                string dateStr2 = date2.Year.ToString() +
                                  (date2.Month >= 10 ? date2.Month.ToString() : "0" + date2.Month.ToString()) +
                                  (date2.Day >= 10 ? date2.Day.ToString() : "0" + date2.Day.ToString());
                char[] dateChar1 = dateStr1.ToCharArray();
                char[] dateChar2 = dateStr2.ToCharArray();
                List<int> mismatchedPositions = new List<int>();
                BitArray bits = new BitArray(dateChar1.Length);
                bits.SetAll(true);
                for (int i = 0; i < bits.Length; i++)
                {
                    if (dateChar1[i] != dateChar2[i])
                    {
                        bits[i] = false;
                        mismatchedPositions.Add(i);
                    }
                }
                if (mismatchedPositions.Count == 1)
                {
                    return 0.65;
                }
                else if (mismatchedPositions.Count == 2)
                {
                    char firstChar1 = dateChar1[mismatchedPositions[0]];
                    char firstChar2 = dateChar2[mismatchedPositions[0]];
                    char secondChar1 = dateChar1[mismatchedPositions[1]];
                    char secondChar2 = dateChar2[mismatchedPositions[1]];
                    if (firstChar1 == secondChar2 && firstChar2 == secondChar1)
                        return 0.60;
                }

                result = MatchResult.NegativeMatch;
                return 0;
            }
        }

        public double Compare(Entity entity1, Entity entity2, AttributeMetaData attrMetaData, ref MatchResult result)
        {
           
            Debug.Assert(!string.IsNullOrEmpty(attrMetaData.AttributeName));

            string attrName = attrMetaData.AttributeName;
            object attrValue1 = null;
            object attrValue2 = null;
            if (entity1.ComparableAttributes.ContainsKey(attrName))
                attrValue1 = entity1.ComparableAttributes[attrName];
            if (entity2.ComparableAttributes.ContainsKey(attrName))
                attrValue2 = entity2.ComparableAttributes[attrName];
            return this.Compare(attrValue1, attrValue2, ref result);
        }

        public string[] ArgumentNames
        {
            get
            {
                return new string[] {"Date"};
            }
        }

        public Dictionary<string, string> ComparerSettings
        {
            get { return new Dictionary<string, string>(); }
            set {  }
        }

        #endregion
    }
}
